#include "stdafx.h"
#include "RetrySenderTestSuite.h"
#include "TestActiveObject.h"

namespace CO { namespace SpiFoundation { namespace RoomFW {

using namespace SpiControl::Protocol;

RetrySenderTestSuite::RetrySenderTestSuite(void)
{
	LOG_TEST_ADD(RetrySenderTestSuite::main)
}

void RetrySenderTestSuite::setup()
{
	LoggedTestSuite::setup();
}

void RetrySenderTestSuite::tear_down()
{
	LoggedTestSuite::tear_down();
}

//
// Test delay response.  Takes in int message with timeout to respond with void message.
//
class DelayResponder : public TestActiveObject
{
public:
	DelayResponder() : 	TestActiveObject("DelayResponder"), retrySender_(this)
	{
		this->mapMessageHandler(PORT_TIMER, ActiveObject::MessageHandler::Ptr(&retrySender_, RetrySender::NullDeleter()));
	}
	virtual void handle(RoomMessageSP message)
	{
		switch (message->portIndex().port())
		{
		case PORT_MY_PORT_1:
			{
				switch (message->messageID())
				{
				case GenericTestProtocol::IN_INT_MESSAGE1:
					{
						IntPayloadSP payload = ::boost::dynamic_pointer_cast<IntPayload, IPayload>(message->releasePayload());
						ASSERT(0 != payload);
						retrySender_.delaySend(payload->value(), PORT_MY_PORT_1, GenericTestProtocol::OUT_VOID_MESSAGE1);
					}
					break;
				}
			}
			break;
		}
	}
private:
	RetrySender retrySender_;
};
typedef ::boost::shared_ptr<DelayResponder> DelayResponderSP;

void RetrySenderTestSuite::main(void)
{
	// Set up the AO and portal.
	DelayResponderSP responder(new DelayResponder());
	EventPortalSP senderPortal(new EventPortal("senderPortal"));
	TEST_ASSERT(senderPortal->initialize());
	BindingList bindings;
	bindings.push_back(PortalBindingSP(new PortalBinding(senderPortal, responder, TestActiveInterface::PORT_MY_PORT_1)));

	// Run the test.
	TEST_ASSERT(responder->start(DWait));

	// Try several different timeouts.
	int timeout = 250;
	for (int i = 0; i < 4; ++i)
	{
		DWORD startTime = ::GetTickCount();
		senderPortal->sendMessage(GenericTestProtocol::IN_INT_MESSAGE1,
			IPayload::ReleaseOwnership(IntPayloadSP(new IntPayload(timeout))));
		TEST_ASSERT(senderPortal->wait(DWait));
		// 15 ms resolution timer -> really 30 ms + extra for processing.  Still << timeout.
		TEST_ASSERT_DELTA(timeout, WindowsUtility::DiffTickCount(startTime), 50);
		RoomMessageSP reply = senderPortal->getMessage();
		TEST_ASSERT(0 != reply);
		TEST_ASSERT(GenericTestProtocol::OUT_VOID_MESSAGE1 == reply->messageID());
		timeout += 250;
	}
	TEST_ASSERT(responder->stop(DWait));
}

}}}
